package com.example.wechat.login.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.wechat.login.config.SpeechHistoryConfig;
import com.example.wechat.login.dto.speech.SpeechRecognitionResponse;
import com.example.wechat.login.dto.speech.SpeechTaskResponse;
import com.example.wechat.login.entity.SpeechRecognitionHistory;
import com.example.wechat.login.mapper.SpeechRecognitionHistoryMapper;
import com.example.wechat.login.service.SpeechRecognitionHistoryService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import java.util.Optional;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

/**
 * 语音识别历史记录服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SpeechRecognitionHistoryServiceImpl extends ServiceImpl<SpeechRecognitionHistoryMapper, SpeechRecognitionHistory> implements SpeechRecognitionHistoryService {

    private final SpeechRecognitionHistoryMapper historyMapper;
    private final SpeechHistoryConfig historyConfig;
    

    
    @Override
    public String saveAudioFile(MultipartFile file, String filename) throws IOException {
        // 确保存储目录存在
        Path storagePath = Paths.get(historyConfig.getFileStoragePath());
        if (!Files.exists(storagePath)) {
            Files.createDirectories(storagePath);
        }
        
        // 保存文件
        Path filePath = storagePath.resolve(filename);
        file.transferTo(filePath.toFile());
        
        return filePath.toString();
    }
    
    @Override
    public SpeechRecognitionResponse recognizeAudio(MultipartFile file, String engineType) throws IOException {
        // 这里应该调用实际的语音识别服务
        // 由于没有具体的语音识别服务实现，这里创建一个模拟实现
        
        log.info("正在使用 {} 引擎识别音频文件: {}", engineType, file.getOriginalFilename());
        
        // 模拟识别过程
        try {
            // 模拟处理时间
            Thread.sleep(1000);
            
            // 创建模拟响应
            return SpeechRecognitionResponse.builder()
                    .requestId(UUID.randomUUID().toString())
                    .result("这是一个模拟的语音识别结果，实际应用中应该调用相应的语音识别服务。")
                    .audioTime((double) 5000L) // 假设音频时长为5秒
                    .build();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new IOException("语音识别过程被中断", e);
        } catch (Exception e) {
            log.error("语音识别失败", e);
            throw new IOException("语音识别失败: " + e.getMessage(), e);
        }
    }
    
    @Override
    public long countByOpenid(String openid) {
        return historyMapper.selectCount(new QueryWrapper<SpeechRecognitionHistory>().eq("openid", openid));
    }

    @Override
    @Transactional
    public SpeechRecognitionHistory saveHistory(String openid, String taskId,String requestId, MultipartFile audioFile) {
        try {
            // 创建历史记录实体
            SpeechRecognitionHistory history = new SpeechRecognitionHistory();
            history.setOpenid(openid);
//            history.setRecognitionResult(result);
            history.setEngineType("tengxun");

            // 如果有音频文件且配置允许保存，则保存文件并记录相关信息
            if (audioFile != null && !audioFile.isEmpty() && historyConfig.isSaveAudioFile()) {
                String originalFilename = audioFile.getOriginalFilename();
                String fileExtension = StringUtils.getFilenameExtension(originalFilename);
                if (fileExtension == null) {
                    fileExtension = "wav"; // 默认扩展名
                }
                
                // 检查文件格式是否允许
                List<String> allowedFormats = Arrays.asList(historyConfig.getAllowedAudioFormats().split(","));
                if (!allowedFormats.contains(fileExtension.toLowerCase())) {
                    throw new IllegalArgumentException("不支持的音频格式: " + fileExtension);
                }
                
                // 检查文件大小是否超过限制
                if (historyConfig.getMaxAudioFileSize() > 0 && audioFile.getSize() > historyConfig.getMaxAudioFileSize()) {
                    throw new IllegalArgumentException("音频文件大小超过限制: " + audioFile.getSize() + " > " + historyConfig.getMaxAudioFileSize());
                }

                // 生成唯一文件名
                String uniqueFileName = generateUniqueFileName(openid, fileExtension);
                
                // 确保存储目录存在
                Path storagePath = Paths.get(historyConfig.getFileStoragePath());
                if (!Files.exists(storagePath)) {
                    Files.createDirectories(storagePath);
                }
                
                // 保存文件
                Path filePath = storagePath.resolve(uniqueFileName);
                audioFile.transferTo(filePath.toFile());
                
                // 设置音频文件信息
                history.setAudioFileName(originalFilename);
                history.setAudioFilePath(filePath.toString());
                history.setAudioFileSize(audioFile.getSize());
                history.setAudioFormat(fileExtension);
                history.setRequestId(requestId);
                
                // TODO: 可以添加获取音频时长和声道数的逻辑
                history.setChannelNum(1); // 默认单声道
                history.setStatus(0);
                history.setTaskId(taskId);
            }
            
            // 检查用户历史记录数量限制
            if (historyConfig.getMaxUserHistoryCount() > 0) {
                long count = historyMapper.countByOpenid(openid);
                if (count >= historyConfig.getMaxUserHistoryCount()) {
                    // 删除最早的记录
                    List<SpeechRecognitionHistory> oldestRecords = historyMapper.selectList(new QueryWrapper<SpeechRecognitionHistory>().eq("openid", openid).orderByAsc("create_time"));
                    if (!oldestRecords.isEmpty()) {
                        int recordsToDelete = (int) (count - historyConfig.getMaxUserHistoryCount() + 1);
                        for (int i = 0; i < recordsToDelete && i < oldestRecords.size(); i++) {
                            deleteById(oldestRecords.get(i).getId());
                        }
                    }
                }
            }

            // 保存历史记录
            historyMapper.insert(history);
        return history;
        } catch (IOException e) {
            log.error("保存语音识别历史记录失败", e);
            throw new RuntimeException("保存语音识别历史记录失败: " + e.getMessage());
        }
    }

    @Override
    public SpeechRecognitionHistory findById(Long id) {
        return Optional.ofNullable(historyMapper.selectById(id))
                .orElseThrow(() -> new RuntimeException("未找到ID为" + id + "的语音识别历史记录"));
    }

    @Override
    public List<SpeechRecognitionHistory> findByOpenid(String openid) {
        return historyMapper.selectList(new QueryWrapper<SpeechRecognitionHistory>().eq("openid", openid).orderByDesc("create_time"));
    }

    @Override
    public SpeechRecognitionHistory findByTaskId(String taskId) {
        return historyMapper.selectOne(new QueryWrapper<SpeechRecognitionHistory>().eq("task_id", taskId));
    }

    @Override
    public SpeechRecognitionHistory findByRequestId(String requestId) {
        return historyMapper.selectOne(new QueryWrapper<SpeechRecognitionHistory>().eq("request_id", requestId));
    }


    @Override
    public List<SpeechRecognitionHistory> findByOpenidAndTimeRange(String openid, LocalDateTime startTime, LocalDateTime endTime) {
        return historyMapper.selectList(new QueryWrapper<SpeechRecognitionHistory>().eq("openid", openid).between("create_time", startTime, endTime).orderByDesc("create_time"));
    }

    @Override
    public List<SpeechRecognitionHistory> findByOpenidAndAudioFormat(String openid, String audioFormat) {
        return historyMapper.selectList(new QueryWrapper<SpeechRecognitionHistory>().eq("openid", openid).eq("audio_format", audioFormat).orderByDesc("create_time"));
    }

    @Override
    public List<SpeechRecognitionHistory> findByOpenidAndEngineType(String openid, String engineType) {
        return historyMapper.selectList(new QueryWrapper<SpeechRecognitionHistory>().eq("openid", openid).eq("engine_type", engineType).orderByDesc("create_time"));
    }

    @Override
    @Transactional
    public void deleteById(Long id) {
        SpeechRecognitionHistory history = findById(id);

        // 如果有音频文件，删除文件
        if (history.getAudioFilePath() != null) {
            try {
                File audioFile = new File(history.getAudioFilePath());
                if (audioFile.exists()) {
                    boolean deleted = audioFile.delete();
                    if (!deleted) {
                        log.warn("无法删除音频文件: {}", history.getAudioFilePath());
                    }
                }
            } catch (Exception e) {
                log.error("删除音频文件失败", e);
            }
        }

        // 删除历史记录
        historyMapper.deleteById(id);
    }

    @Override
    @Transactional
    public void deleteByOpenid(String openid) {
        // 查找该用户的所有历史记录
        List<SpeechRecognitionHistory> historyList = findByOpenid(openid);

        // 删除关联的音频文件
        for (SpeechRecognitionHistory history : historyList) {
            if (history.getAudioFilePath() != null) {
                try {
                    File audioFile = new File(history.getAudioFilePath());
                    if (audioFile.exists()) {
                        boolean deleted = audioFile.delete();
                        if (!deleted) {
                            log.warn("无法删除音频文件: {}", history.getAudioFilePath());
                        }
                    }
                } catch (Exception e) {
                    log.error("删除音频文件失败", e);
                }
            }
        }

        // 删除历史记录
        historyMapper.delete(new QueryWrapper<SpeechRecognitionHistory>().eq("openid", openid));
    }

    @Override
    @Transactional
    public void deleteByOpenidAndTimeRange(String openid, LocalDateTime startTime, LocalDateTime endTime) {
        // 查找指定时间范围内的历史记录
        List<SpeechRecognitionHistory> historyList = findByOpenidAndTimeRange(openid, startTime, endTime);

        // 删除关联的音频文件
        for (SpeechRecognitionHistory history : historyList) {
            if (history.getAudioFilePath() != null) {
                try {
                    File audioFile = new File(history.getAudioFilePath());
                    if (audioFile.exists()) {
                        boolean deleted = audioFile.delete();
                        if (!deleted) {
                            log.warn("无法删除音频文件: {}", history.getAudioFilePath());
                        }
                    }
                } catch (Exception e) {
                    log.error("删除音频文件失败", e);
                }
            }
        }

        // 删除历史记录
        historyMapper.delete(new QueryWrapper<SpeechRecognitionHistory>().eq("openid", openid).between("create_time", startTime, endTime));
    }

    @Override
    public Integer updateTask(SpeechTaskResponse updatedTask) {
        String taskId = updatedTask.getTaskId();
        SpeechRecognitionHistory byTaskId = findByTaskId(taskId);
        if (byTaskId != null) {
            byTaskId.setStatus(updatedTask.getStatus());
            byTaskId.setRecognitionResult(updatedTask.getResult());
            historyMapper.updateById(byTaskId);
            return 1;
        }
        return 0;
    }

    @Override
    @Transactional
    public void update(SpeechRecognitionHistory task) {
        historyMapper.updateById( task);
    }

    /**
     * 生成唯一的文件名
     *
     * @param openid 用户openid
     * @param fileExtension 文件扩展名
     * @return 唯一文件名
     */
    private String generateUniqueFileName(String openid, String fileExtension) {
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String uuid = UUID.randomUUID().toString().substring(0, 8);
        return openid + "_" + timestamp + "_" + uuid + "." + fileExtension;
    }
}
